The venerable Western Hemlock has been in decline in the Puget Lowlands since 2015. Researchers initially believed this novel mortality was caused by Rhizoctonia butini, a fungus in the order Cantharellales. This hypothesis has since fallen out of favor (Jared LeBoldus, OSU Corvallis, personal communication). No replacement theory has arisen.
Scientists and citizens oftne suggest that the mortality is due simply to old age - normal senescence - or to changes in weather patterns related to climate change.
As with the sword fern blight, Seward Park’s old-growth urban forest presents an opportunity to study the hemlock decline.
The 120 acre forest forest has approximately 1000 hemlocks of all ages. Healthy hemlocks are common, newborn seedlings to four foot diameter 250 year odl giants. Diseased, dead and dying hemlocks are common also, and appear to be concentrated in the northernmost forest.
Informal observation led forest steward Paul Shannon to suppose that two small (hectare-sized) hemlock-rich sites at Seward may have roughly equivalent age and density distributions, yet radically different health profiles. These contrasting sites may provide an opportunity to study contrasting health and disease, and perhaps to identify the mechanism of the regional hemlock decline. Here confounding factors are eliminated: tree age distributions are similar, weather patterns are identical, mortality is radically diffeent.
In the study reported here, we followed up on Shannon’s informal observations by measuring hundreds of hemlocks of all sizes, ages, locations and health status over three months, from January through March, 2024. This dataset set the stage for tests of statistical signifcance shown below.
These two dense hemlock sites, initially identified by informal inspection, have comparable age distribution - estimated from tree diameter - and contasting health, as these boxplots show. In this analysis, the data are rather crudely separated only on latitude. More nuanced separation appears below.
Subsequent mapping and analysis refined these results - see below.
tbl.graveyard <- subset(tbl, lat >= 47.558934)
tbl.garden <- subset(tbl, lat <= 47.555554)
boxplot(tbl.graveyard$h, tbl.garden$h, names=c("graveyard", "garden"), main="Hemlock Health scaled 0-3")
boxplot(tbl.graveyard$dbh, tbl.garden$dbh, names=c("graveyard", "garden"),
main="Hemlock Diameter (DBH inches) a proxy for age")
Between January and March, two Univeristy of Washington students from the Program on the Environment in their senior Capstone Research Project, along with a Garfield High School junior, spent about 200 hours in the forest, collecting data to test the hypothesis that dense hemlock stands
Here is a screenshot of the resulting interactive map. The blue circles are hand-drawn visual estimates of the boundaries of the two informally identified contrasting sites. These are replaced below by analytically derived boundaries.
Kernel Density solves the “overplotting” problem seen in the map above, in which the overall state of the forest is obscured by the large number of individulally measured and plotted trees. The leftmost plot below shows the density of all hemlocks. The middle shows the density of dead and low health trees. The rightmost plot shows the distribution of healthy hemlocks.
Out next step is to define two sites of
library(MASS)
library(RColorBrewer)
options(digits=12)
f <- "https://pshannon.net/hemlockSurvey2024/tblFinal.csv"
tbl <- read.table(f, sep=",", header=TRUE, as.is=TRUE, nrow=-1, quote="")
# get just the healthy trees
tbl.x <- subset(tbl, h>=2)
min.density <- 30000
cellCount <- 500
osm.limits <- c(-122.25676, -122.248006, 47.548233, 47.562744) # open street map
limits <- osm.limits
f.healthy <- kde2d(tbl.x$lon, tbl.x$lat, n=cellCount, lims=limits)
z <- f.healthy$z
# zero out low density cells
z[z <min.density] <- 0
f.healthy$z <- z
# display if you wish
healthy.colors <- brewer.pal(8, "Greens")
healthy.colors[1] <- "#FFFFFF"
sick.colors <- brewer.pal(8, "Reds")
sick.colors[1] <- "#FFFFFF"
# image(f.healthy, main="healthy", col=healthy.colors) #, zlim = c(0, 0.05))
# can we get the boundary of the highest density region
# from the contour?
tbl.x <- subset(tbl, h<=1)
f.sick <- kde2d(tbl.x$lon, tbl.x$lat, n=cellCount, lims=limits)
z <- f.sick$z
z[z <min.density] <- NA
f.sick$z <- z
range(f.sick$z)
## [1] NA NA
#pdf("sick.pdf")
#image(f.sick, main="sick", add=FALSE, col=sick.colors)
boundaries.sick <- contourLines(f.sick)
boundaries.healthy <- contourLines(f.healthy)
print(as.numeric(unlist(lapply(boundaries.sick, "[", "level"))))
## [1] 40000 50000 60000 60000 70000 80000 90000 100000 110000 120000 130000
print(length(boundaries.sick[[6]]$x))
## [1] 309
print(as.numeric(unlist(lapply(boundaries.healthy, "[", "level"))))
## [1] 10000 20000 30000 40000 50000 50000 60000 70000 80000 90000 100000 110000 120000
## [14] 130000
print(length(boundaries.healthy[[6]]$x))
## [1] 587
# x <- boundaries.sick[[6]]$x
# y <- boundaries.sick[[6]]$y
# for(i in seq_len(length(x))){
# print(sprintf("{lat: %12.8f, lng: %12.8f},", y[i], x[i]))
# }
# x <- boundaries.healthy[[6]]$x
# y <- boundaries.healthy[[6]]$y
# for(i in seq_len(length(x))){
# print(sprintf("{lat: %12.8f, lng: %12.8f},", y[i], x[i]))
# }